Les données avec lequelles nous allons travailler sont les transactions immobilières intervenues au cours des cinq dernières années sur le territoire métropolitain et les DOM-TOM, à l’exception de l'Alsace, de la Moselle et de Mayotte.
Avant de commencer le projet, on importe d'abord les librairies python nécessaires pour l'analyse des données: numpy, pandas matplotlib ou seaborn.
from IPython.display import HTML, display
def set_background(color):
script = ("var cell = this.closest('.code_cell');"
"var editor = cell.querySelector('.input_area');"
"editor.style.background='{}';"
"this.parentNode.removeChild(this)"
).format(color)
display(HTML('<img src onerror="{}">'.format(script)))
set_background('#E9FDFF')
Source pour changement de couleur : https://www.kaggle.com/code/alejopaullier/make-your-notebooks-look-better#6.-Change-cell-background-colors--%E2%86%91
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.express as px
import folium
set_background('#E9FDFF')
Pour pouvoir travailler sur les données nous allons les charger le fichier "valeursfoncieres-2022.txt" dans une variable valeurs_foncieres avec l'aide d'une méthode pandas qui s'appelle read_csv(). On va devoir nettoyer, filtrer et modifier pour préparer un data frame qui est prêt à être analysé.
df = pd.read_csv('valeursfoncieres-2022.txt',sep='|')
print(df.shape[0])
set_background('#E9FDFF')
3803885
print("Dataframe 2022 : il y a", df.shape[0], "lignes et", df.shape[1], "colonnes")
set_background('#E9FDFF')
Dataframe 2022 : il y a 3803885 lignes et 43 colonnes
Première visualisation de notre Dataframe 2022 :
set_background('#E9FDFF')
df.head(10)
| Identifiant de document | Reference document | 1 Articles CGI | 2 Articles CGI | 3 Articles CGI | 4 Articles CGI | 5 Articles CGI | No disposition | Date mutation | Nature mutation | Valeur fonciere | No voie | B/T/Q | Type de voie | Code voie | Voie | Code postal | Commune | Code departement | Code commune | Prefixe de section | Section | No plan | No Volume | 1er lot | Surface Carrez du 1er lot | 2eme lot | Surface Carrez du 2eme lot | 3eme lot | Surface Carrez du 3eme lot | 4eme lot | Surface Carrez du 4eme lot | 5eme lot | Surface Carrez du 5eme lot | Nombre de lots | Code type local | Type local | Identifiant local | Surface reelle bati | Nombre pieces principales | Nature culture | Nature culture speciale | Surface terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 55000,00 | 13.0 | NaN | RUE | 2280 | DE LA LIBERTE | 1000.0 | BOURG-EN-BRESSE | 1 | 53 | NaN | AM | 102 | NaN | 7 | 24,10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 2.0 | Appartement | NaN | 24.0 | 1.0 | NaN | NaN | NaN |
| 1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 184 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 84.0 |
| 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 185 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 88.0 |
| 3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | 98.0 | NaN | RTE | 0055 | DE LA DOMBES | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 187 | NaN | 1 | 123,23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 2.0 | Appartement | NaN | 140.0 | 3.0 | NaN | NaN | NaN |
| 4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 04/01/2022 | Vente | 300,00 | NaN | NaN | NaN | B031 | AUX PIERRES | 1480.0 | MESSIMY SUR SAONE | 1 | 243 | NaN | A | 643 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | T | NaN | 510.0 |
| 5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 06/01/2022 | Vente | 255000,00 | 282.0 | NaN | RTE | 0130 | DE POISATON | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | NaN | ZM | 124 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 1.0 | Maison | NaN | 108.0 | 5.0 | S | NaN | 649.0 |
| 6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 06/01/2022 | Vente | 255000,00 | NaN | NaN | NaN | B047 | LA FREGONIERE | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | NaN | ZM | 126 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 360.0 |
| 7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | NaN | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 50.0 |
| 8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 186 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 4.0 | Local industriel. commercial ou assimilé | NaN | 424.0 | 0.0 | S | NaN | 628.0 |
| 9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 186 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 2.0 | Appartement | NaN | 126.0 | 4.0 | S | NaN | 628.0 |
On remarque qu'il y a trois pointillés dans les colonnes de notre DataFrame. Pour corriger ça on peut utiliser la méthode set_option qui va augmenter le nombre de colonne visible et ainsi nous permettre de visualiser l'entierté des colonnes.
set_background('#E9FDFF')
pd.set_option('max_columns',50)
set_background('#E9FDFF')
df.head(10)
| Identifiant de document | Reference document | 1 Articles CGI | 2 Articles CGI | 3 Articles CGI | 4 Articles CGI | 5 Articles CGI | No disposition | Date mutation | Nature mutation | Valeur fonciere | No voie | B/T/Q | Type de voie | Code voie | Voie | Code postal | Commune | Code departement | Code commune | Prefixe de section | Section | No plan | No Volume | 1er lot | Surface Carrez du 1er lot | 2eme lot | Surface Carrez du 2eme lot | 3eme lot | Surface Carrez du 3eme lot | 4eme lot | Surface Carrez du 4eme lot | 5eme lot | Surface Carrez du 5eme lot | Nombre de lots | Code type local | Type local | Identifiant local | Surface reelle bati | Nombre pieces principales | Nature culture | Nature culture speciale | Surface terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 55000,00 | 13.0 | NaN | RUE | 2280 | DE LA LIBERTE | 1000.0 | BOURG-EN-BRESSE | 1 | 53 | NaN | AM | 102 | NaN | 7 | 24,10 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 2.0 | Appartement | NaN | 24.0 | 1.0 | NaN | NaN | NaN |
| 1 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 184 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 84.0 |
| 2 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 185 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 88.0 |
| 3 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 143000,00 | 98.0 | NaN | RTE | 0055 | DE LA DOMBES | 1480.0 | SAVIGNEUX | 1 | 398 | NaN | ZE | 187 | NaN | 1 | 123,23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 2.0 | Appartement | NaN | 140.0 | 3.0 | NaN | NaN | NaN |
| 4 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 04/01/2022 | Vente | 300,00 | NaN | NaN | NaN | B031 | AUX PIERRES | 1480.0 | MESSIMY SUR SAONE | 1 | 243 | NaN | A | 643 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | T | NaN | 510.0 |
| 5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 06/01/2022 | Vente | 255000,00 | 282.0 | NaN | RTE | 0130 | DE POISATON | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | NaN | ZM | 124 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 1.0 | Maison | NaN | 108.0 | 5.0 | S | NaN | 649.0 |
| 6 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 06/01/2022 | Vente | 255000,00 | NaN | NaN | NaN | B047 | LA FREGONIERE | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | NaN | ZM | 126 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 360.0 |
| 7 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | NaN | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | NaN | S | NaN | 50.0 |
| 8 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 186 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 4.0 | Local industriel. commercial ou assimilé | NaN | 424.0 | 0.0 | S | NaN | 628.0 |
| 9 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | NaN | AN | 186 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0 | 2.0 | Appartement | NaN | 126.0 | 4.0 | S | NaN | 628.0 |
Ce DataFrame contient beaucoup de colonnes, on peut donc tous les voir avec valeurs_foncieres.columns
set_background('#E9FDFF')
df.columns
Index(['Identifiant de document', 'Reference document', '1 Articles CGI',
'2 Articles CGI', '3 Articles CGI', '4 Articles CGI', '5 Articles CGI',
'No disposition', 'Date mutation', 'Nature mutation', 'Valeur fonciere',
'No voie', 'B/T/Q', 'Type de voie', 'Code voie', 'Voie', 'Code postal',
'Commune', 'Code departement', 'Code commune', 'Prefixe de section',
'Section', 'No plan', 'No Volume', '1er lot',
'Surface Carrez du 1er lot', '2eme lot', 'Surface Carrez du 2eme lot',
'3eme lot', 'Surface Carrez du 3eme lot', '4eme lot',
'Surface Carrez du 4eme lot', '5eme lot', 'Surface Carrez du 5eme lot',
'Nombre de lots', 'Code type local', 'Type local', 'Identifiant local',
'Surface reelle bati', 'Nombre pieces principales', 'Nature culture',
'Nature culture speciale', 'Surface terrain'],
dtype='object')
set_background('#E9FDFF')
df.dtypes
Identifiant de document float64 Reference document float64 1 Articles CGI float64 2 Articles CGI float64 3 Articles CGI float64 4 Articles CGI float64 5 Articles CGI float64 No disposition int64 Date mutation object Nature mutation object Valeur fonciere object No voie float64 B/T/Q object Type de voie object Code voie object Voie object Code postal float64 Commune object Code departement object Code commune int64 Prefixe de section float64 Section object No plan int64 No Volume object 1er lot object Surface Carrez du 1er lot object 2eme lot object Surface Carrez du 2eme lot object 3eme lot object Surface Carrez du 3eme lot object 4eme lot float64 Surface Carrez du 4eme lot object 5eme lot float64 Surface Carrez du 5eme lot object Nombre de lots int64 Code type local float64 Type local object Identifiant local float64 Surface reelle bati float64 Nombre pieces principales float64 Nature culture object Nature culture speciale object Surface terrain float64 dtype: object
La plupart des colonnes ont un type "object", soit parcequ'ils contiennent des valeurs de différents types ou qu'ils contiennent des valeurs vides, qui sont représentées par le NaN . On va devoir s'occuper des valeurs nulls et ajuster les types des données manuellement de quelques colonnes.
set_background('#E9FDFF')
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 3803885 entries, 0 to 3803884 Data columns (total 43 columns): # Column Dtype --- ------ ----- 0 Identifiant de document float64 1 Reference document float64 2 1 Articles CGI float64 3 2 Articles CGI float64 4 3 Articles CGI float64 5 4 Articles CGI float64 6 5 Articles CGI float64 7 No disposition int64 8 Date mutation object 9 Nature mutation object 10 Valeur fonciere object 11 No voie float64 12 B/T/Q object 13 Type de voie object 14 Code voie object 15 Voie object 16 Code postal float64 17 Commune object 18 Code departement object 19 Code commune int64 20 Prefixe de section float64 21 Section object 22 No plan int64 23 No Volume object 24 1er lot object 25 Surface Carrez du 1er lot object 26 2eme lot object 27 Surface Carrez du 2eme lot object 28 3eme lot object 29 Surface Carrez du 3eme lot object 30 4eme lot float64 31 Surface Carrez du 4eme lot object 32 5eme lot float64 33 Surface Carrez du 5eme lot object 34 Nombre de lots int64 35 Code type local float64 36 Type local object 37 Identifiant local float64 38 Surface reelle bati float64 39 Nombre pieces principales float64 40 Nature culture object 41 Nature culture speciale object 42 Surface terrain float64 dtypes: float64(17), int64(4), object(22) memory usage: 1.2+ GB
Maintenant qu'on a une idée globale de notre DataFrame, on va d'abord faire un peu de nettoyage de données avant d'entrer dans l'analyse.
En affichant notre DataFrame avec la méthode head() on a remarqué qu'il y avait beaucoup de valeurs manquantes, surtout pour les 7 premiers colonnes et la colonne "Identifiant local". En regardant le pourcentage de valeurs manquantes on remarque que plusieurs des colonnes contiennent plus de 90% de valeurs manquantes.
valeurs_manquantes = df.isnull().sum() / df.shape[0] * 100
valeurs_manquantes_sorted = valeurs_manquantes.sort_values()
plt.figure(figsize=(10, 8))
plt.barh(valeurs_manquantes_sorted.index, valeurs_manquantes_sorted)
for i, v in enumerate(valeurs_manquantes_sorted):
plt.text(v, i, str(round(v,2)) + '%', color='black', fontsize=10, ha='left', va='center')
plt.title("Pourcentage de valeurs manquantes par colonne")
plt.xlabel("Pourcentage de valeurs manquantes")
plt.ylabel("Colonnes")
plt.show()
set_background('#E9FDFF')
ous allons d'abord supprimer les colonnes avec 100% de valeurs manquantes avec la méthode drop.
Ensuite pour le reste des colonnes, on doit prendre en contexte notre analyse et réflechir à l'utilité potentielle de chaque colonne avant de les supprimer définitivement.
"B/T/Q", "Prefixe de section", "No Volume", "2eme lot", "Surface Carrez du 2eme lot", "3eme lot", "Surface Carrez du 3eme lot", "4eme lot", "Surface Carrez du 4eme lot", "5eme lot", et "Surface Carrez du 5eme lot". Ces colonnes ne semblent pas contenir des informations pertinentes pour l'analyse, il serait donc probablement judicieux de les supprimer.
set_background('#E9FDFF')
drop_columns = [
'Identifiant de document',
'Reference document',
'1 Articles CGI',
'2 Articles CGI',
'3 Articles CGI',
'4 Articles CGI',
'5 Articles CGI',
'Identifiant local',
'B/T/Q',
'Prefixe de section',
'No Volume',
'2eme lot',
'Surface Carrez du 2eme lot',
'3eme lot',
'Surface Carrez du 3eme lot',
'4eme lot',
'Surface Carrez du 4eme lot',
'5eme lot',
'Surface Carrez du 5eme lot'
]
df.drop(drop_columns, inplace = True, axis=1)
set_background('#E9FDFF')
df.head(10)
| No disposition | Date mutation | Nature mutation | Valeur fonciere | No voie | Type de voie | Code voie | Voie | Code postal | Commune | Code departement | Code commune | Section | No plan | 1er lot | Surface Carrez du 1er lot | Nombre de lots | Code type local | Type local | Surface reelle bati | Nombre pieces principales | Nature culture | Nature culture speciale | Surface terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 03/01/2022 | Vente | 55000,00 | 13.0 | RUE | 2280 | DE LA LIBERTE | 1000.0 | BOURG-EN-BRESSE | 1 | 53 | AM | 102 | 7 | 24,10 | 1 | 2.0 | Appartement | 24.0 | 1.0 | NaN | NaN | NaN |
| 1 | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 184 | NaN | NaN | 0 | NaN | NaN | NaN | NaN | S | NaN | 84.0 |
| 2 | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 185 | NaN | NaN | 0 | NaN | NaN | NaN | NaN | S | NaN | 88.0 |
| 3 | 1 | 03/01/2022 | Vente | 143000,00 | 98.0 | RTE | 0055 | DE LA DOMBES | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 187 | 1 | 123,23 | 1 | 2.0 | Appartement | 140.0 | 3.0 | NaN | NaN | NaN |
| 4 | 1 | 04/01/2022 | Vente | 300,00 | NaN | NaN | B031 | AUX PIERRES | 1480.0 | MESSIMY SUR SAONE | 1 | 243 | A | 643 | NaN | NaN | 0 | NaN | NaN | NaN | NaN | T | NaN | 510.0 |
| 5 | 1 | 06/01/2022 | Vente | 255000,00 | 282.0 | RTE | 0130 | DE POISATON | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | ZM | 124 | NaN | NaN | 0 | 1.0 | Maison | 108.0 | 5.0 | S | NaN | 649.0 |
| 6 | 1 | 06/01/2022 | Vente | 255000,00 | NaN | NaN | B047 | LA FREGONIERE | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | ZM | 126 | NaN | NaN | 0 | NaN | NaN | NaN | NaN | S | NaN | 360.0 |
| 7 | 1 | 03/01/2022 | Vente | 525000,00 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 23 | NaN | NaN | 0 | NaN | NaN | NaN | NaN | S | NaN | 50.0 |
| 8 | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 186 | NaN | NaN | 0 | 4.0 | Local industriel. commercial ou assimilé | 424.0 | 0.0 | S | NaN | 628.0 |
| 9 | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 186 | NaN | NaN | 0 | 2.0 | Appartement | 126.0 | 4.0 | S | NaN | 628.0 |
On peut aussi vérifier si le DataFrame contient des lignes avec que des valeurs NaN.
df.dropna(axis = 0,how = 'all')
set_background('#E9FDFF')
3803885
On peut aussi prendre le soin de renommer nos colonnes avec la méthode rename:
df = pd.read_csv("valeursfoncieres-2022.txt",sep="|",usecols=["No disposition",
"Date mutation",
"Nature mutation",
"Valeur fonciere",
"No voie",
"B/T/Q",
"Type de voie",
"Code voie",
"Voie",
"Code postal",
"Commune",
"Code departement",
"Code commune",
"Section",
"No plan",
"Nombre de lots",
"Code type local",
"Type local",
"Surface reelle bati",
"Nombre pieces principales",
"Nature culture",
"Surface terrain"])
df.columns = ["NoDisposition","DateMutation","NatureMutation","ValeurFonciere","NoVoie","BTQ","TypeDeVoie","CodeVoie","Voie","CodePostal","Commune","CodeDepartement","CodeCommune","Section","NoPlan","NombreDeLots","CodeTypeLocal","TypeLocal","SurfaceReelleBati","NombrePiecesPrincipales","NatureCulture","SurfaceTerrain"]
set_background('#E9FDFF')
C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (18) have mixed types.Specify dtype option on import or set low_memory=False. has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
set_background('#E9FDFF')
df.head(10)
| NoDisposition | DateMutation | NatureMutation | ValeurFonciere | NoVoie | BTQ | TypeDeVoie | CodeVoie | Voie | CodePostal | Commune | CodeDepartement | CodeCommune | Section | NoPlan | NombreDeLots | CodeTypeLocal | TypeLocal | SurfaceReelleBati | NombrePiecesPrincipales | NatureCulture | SurfaceTerrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 03/01/2022 | Vente | 55000,00 | 13.0 | NaN | RUE | 2280 | DE LA LIBERTE | 1000.0 | BOURG-EN-BRESSE | 1 | 53 | AM | 102 | 1 | 2.0 | Appartement | 24.0 | 1.0 | NaN | NaN |
| 1 | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 184 | 0 | NaN | NaN | NaN | NaN | S | 84.0 |
| 2 | 1 | 03/01/2022 | Vente | 143000,00 | NaN | NaN | NaN | B010 | CHAMP COCHET | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 185 | 0 | NaN | NaN | NaN | NaN | S | 88.0 |
| 3 | 1 | 03/01/2022 | Vente | 143000,00 | 98.0 | NaN | RTE | 0055 | DE LA DOMBES | 1480.0 | SAVIGNEUX | 1 | 398 | ZE | 187 | 1 | 2.0 | Appartement | 140.0 | 3.0 | NaN | NaN |
| 4 | 1 | 04/01/2022 | Vente | 300,00 | NaN | NaN | NaN | B031 | AUX PIERRES | 1480.0 | MESSIMY SUR SAONE | 1 | 243 | A | 643 | 0 | NaN | NaN | NaN | NaN | T | 510.0 |
| 5 | 1 | 06/01/2022 | Vente | 255000,00 | 282.0 | NaN | RTE | 0130 | DE POISATON | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | ZM | 124 | 0 | 1.0 | Maison | 108.0 | 5.0 | S | 649.0 |
| 6 | 1 | 06/01/2022 | Vente | 255000,00 | NaN | NaN | NaN | B047 | LA FREGONIERE | 1560.0 | MANTENAY-MONTLIN | 1 | 230 | ZM | 126 | 0 | NaN | NaN | NaN | NaN | S | 360.0 |
| 7 | 1 | 03/01/2022 | Vente | 525000,00 | NaN | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 23 | 0 | NaN | NaN | NaN | NaN | S | 50.0 |
| 8 | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 186 | 0 | 4.0 | Local industriel. commercial ou assimilé | 424.0 | 0.0 | S | 628.0 |
| 9 | 1 | 03/01/2022 | Vente | 525000,00 | 217.0 | NaN | PL | 0300 | DE LA CROIX BLANCHE | 1390.0 | SAINT-ANDRE-DE-CORCY | 1 | 333 | AN | 186 | 0 | 2.0 | Appartement | 126.0 | 4.0 | S | 628.0 |
Nous changeons les types de ValeurFonciere et CodeDepartement pour les analyses suivantes
Nous pouvons changer les types de certains "Series" comme par exemple pour la Valeur Fonciere. On veut aussi changer le type d'autres colonnes mais comme ils ont des valeurs NaN ce n'est pas possible. On a donc pris la décision de garder un type float pour les colonnes comme No Voie, Code Postal ou encore Nbr pieces principales.
df["ValeurFonciere"] = df["ValeurFonciere"].apply(lambda x : x if isinstance(x, float) else float(x[:-3]))
df["CodeDepartement"] = pd.to_numeric(df["CodeDepartement"], errors = 'coerce')
set_background('#E9FDFF')
Maintenant qu'on a charger, nettoyer, filtrer et modifier les données, on peut avancer à la prochaine étape qui est l'analyse.
ValeurFonciereMoyenne = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne)})
ValeurFonciereMoyenne.drop([91,92,93,94],axis=0,inplace=True)
fig, ax = plt.subplots(figsize=(12,8))
ax.bar(ValeurFonciereMoyenne['Departement'], ValeurFonciereMoyenne['ValeurFonciere'])
ax.set_title('Valeur foncière moyenne par département', fontsize=18)
ax.set_xlabel('Département', fontsize=14)
ax.set_ylabel('Valeur foncière moyenne', fontsize=14)
ax.grid(axis='x')
plt.show()
set_background('#E9FDFF')
Ce graphique semble abbérant au niveau du département 22 :
On analyse le département 22 et les données des 20 biens vendus dans ce département avec la plus grande valeur foncière.
print("La valeur foncière moyenne du département 22 est de : " + str(df.loc[df['CodeDepartement'] == 22]['ValeurFonciere'].mean()))
set_background('#E9FDFF')
La valeur foncière moyenne du département 22 est de : 10694890.488300221
set_background('#E9FDFF')
df_22 = df[df['CodeDepartement'] == 22]
valeur_fonciere_22 = df_22.nlargest(20, 'ValeurFonciere')
valeur_fonciere_22
| NoDisposition | DateMutation | NatureMutation | ValeurFonciere | NoVoie | BTQ | TypeDeVoie | CodeVoie | Voie | CodePostal | Commune | CodeDepartement | CodeCommune | Section | NoPlan | NombreDeLots | CodeTypeLocal | TypeLocal | SurfaceReelleBati | NombrePiecesPrincipales | NatureCulture | SurfaceTerrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 670693 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0018 | DES ERABLES | 22400.0 | ANDEL | 22.0 | 2 | ZK | 389 | 0 | 1.0 | Maison | 93.0 | 4.0 | S | 826.0 |
| 670694 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0018 | DES ERABLES | 22400.0 | ANDEL | 22.0 | 2 | ZK | 389 | 0 | 1.0 | Maison | 93.0 | 4.0 | S | 826.0 |
| 670695 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0018 | DES ERABLES | 22400.0 | ANDEL | 22.0 | 2 | ZK | 389 | 0 | 1.0 | Maison | 93.0 | 4.0 | S | 826.0 |
| 670696 | 1 | 14/06/2022 | Vente | 64750612.0 | 5.0 | NaN | RUE | 0155 | DE LA TOUR DU FA | 22120.0 | HILLION | 22.0 | 81 | BB | 27 | 1 | 3.0 | Dépendance | 0.0 | 0.0 | NaN | NaN |
| 670697 | 1 | 14/06/2022 | Vente | 64750612.0 | 5.0 | NaN | RUE | 0155 | DE LA TOUR DU FA | 22120.0 | HILLION | 22.0 | 81 | BB | 27 | 1 | 2.0 | Appartement | 67.0 | 4.0 | NaN | NaN |
| 670698 | 1 | 14/06/2022 | Vente | 64750612.0 | 5.0 | NaN | RUE | 0155 | DE LA TOUR DU FA | 22120.0 | HILLION | 22.0 | 81 | BB | 27 | 1 | 4.0 | Local industriel. commercial ou assimilé | 38.0 | 0.0 | NaN | NaN |
| 670699 | 1 | 14/06/2022 | Vente | 64750612.0 | 8.0 | A | VEN | 0135 | DES PORTES | 22120.0 | HILLION | 22.0 | 81 | BB | 50 | 0 | 1.0 | Maison | 82.0 | 4.0 | S | 316.0 |
| 670700 | 1 | 14/06/2022 | Vente | 64750612.0 | 8.0 | A | VEN | 0135 | DES PORTES | 22120.0 | HILLION | 22.0 | 81 | BB | 50 | 0 | 1.0 | Maison | 82.0 | 4.0 | S | 316.0 |
| 670701 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 2.0 | Appartement | 74.0 | 4.0 | S | 995.0 |
| 670702 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 995.0 |
| 670703 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 995.0 |
| 670704 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 995.0 |
| 670705 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 2.0 | Appartement | 62.0 | 3.0 | S | 995.0 |
| 670706 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 995.0 |
| 670707 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 995.0 |
| 670708 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 2.0 | Appartement | 62.0 | 3.0 | S | 995.0 |
| 670709 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 2.0 | Appartement | 65.0 | 3.0 | S | 995.0 |
| 670710 | 1 | 14/06/2022 | Vente | 64750612.0 | 2.0 | NaN | RUE | 0041 | DU CLOS GUEGUEN | 22120.0 | HILLION | 22.0 | 81 | BB | 167 | 0 | 2.0 | Appartement | 62.0 | 3.0 | S | 995.0 |
| 670711 | 1 | 14/06/2022 | Vente | 64750612.0 | 7.0 | NaN | RUE | 0235 | DE DOUVENANT | 22360.0 | LANGUEUX | 22.0 | 106 | AD | 26 | 0 | 1.0 | Maison | 67.0 | 3.0 | S | 404.0 |
| 670712 | 1 | 14/06/2022 | Vente | 64750612.0 | 41.0 | NaN | RUE | 0222 | DES CYGNES | 22360.0 | LANGUEUX | 22.0 | 106 | AD | 177 | 0 | NaN | NaN | NaN | NaN | S | 33.0 |
df.drop_duplicates(subset=['ValeurFonciere','CodeDepartement', 'DateMutation'], inplace=True)
ValeurFonciereMoyenne = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne)})
ValeurFonciereMoyenne.drop([91,92,93,94],axis=0,inplace=True)
fig = plt.figure(figsize=(12,8))
plt.bar(ValeurFonciereMoyenne['Departement'], ValeurFonciereMoyenne['ValeurFonciere'])
plt.title('Valeur foncière moyenne par département', fontsize=18)
plt.xlabel('Département', fontsize=14)
plt.ylabel('Valeur foncière moyenne', fontsize=14)
set_background('#E9FDFF')
print(df.shape[0])
1279068
ValeurFonciereMoyenne = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
NbVentes = df.groupby("CodeDepartement")["CodeDepartement"].count()
Surface = df.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
ValeurFonciereMoyenne = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne),
"NbVente" : list(NbVentes),
"Surface" : list(Surface)})
fig = px.scatter(ValeurFonciereMoyenne, x='ValeurFonciere', y='Surface', color='NbVente', size='NbVente',
height=700, text='Departement', log_x=True, log_y=True,
color_discrete_sequence=px.colors.qualitative.Vivid,
template='plotly_dark')
fig.update_traces(marker_size=30, marker_line_width=1, opacity=0.7)
fig.update_layout(plot_bgcolor = 'rgb(50,50,50)',
paper_bgcolor = 'rgb(50,50,50)',
font=dict(family="Arial, sans-serif",
size=15,
color="#FFFFFF"))
fig.show()
set_background('#E6E6FA')
Observations On observe que deux département sortent du lot en terme de Valeur Foncière moyenne, et ce sont sans surprise Paris et les Hauts-de Seine (75 et 92) On remarque également que beaucoup plus de biens sont vendus à Paris que dans le 92, comme le prouve les couleurs qui leurs sont associée et la légende de NbVente.
Globalement, on remarque que plus un bien coûte cher (et est sur la droite du graphique), plus sa valeur foncière est élevée, et moins il y a de surface. Autrement dit, il y aurait une droite de régression. </i>
ValeurFonciereMoyenne = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
NbVentes = df.groupby("CodeDepartement")["CodeDepartement"].count()
Surface = df.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
ValeurFonciereMoyenne = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne),
"NbVente" : list(NbVentes*10000),
"Surface" : list(Surface)})
fig = px.scatter(ValeurFonciereMoyenne, x='ValeurFonciere', y='Surface', size='NbVente',
height=700, text='Departement', log_x=True, log_y=True,
title='Graphique à dispersion représentant le nombre de vente de biens dans un département en fonction de la valeur \nfoncière moyenne des biens de ce département',
color_discrete_sequence=px.colors.qualitative.Vivid,
template='plotly_dark')
fig.update_traces(marker_line_width=1, opacity=0.7)
fig.update_layout(plot_bgcolor = 'rgb(50,50,50)',
paper_bgcolor = 'rgb(50,50,50)',
font=dict(family="Arial, sans-serif",
size=15,
color="#FFFFFF"))
fig.show()
set_background('#E6E6FA')
df_grouped = df.groupby('CodeDepartement')['SurfaceReelleBati'].agg(['mean', 'count']).reset_index()
df_grouped = df_grouped.sort_values('mean', ascending=False).head(10)
plt.figure(figsize=(14,8))
sns.barplot(x=df_grouped['CodeDepartement'], y=df_grouped['mean'], palette='viridis', order=df_grouped['CodeDepartement'])
plt.title('Surface reelle bati moyenne du 1er lot par code departement')
plt.xlabel('Code département')
plt.ylabel('Surface reelle bati')
plt.show()
set_background('#E6E6FA')
df_grouped = df.groupby('CodeDepartement')['SurfaceReelleBati'].agg(['mean', 'count']).reset_index()
df_grouped = df_grouped.sort_values('mean', ascending=True)
plt.figure(figsize=(14,8))
sns.barplot(x=df_grouped['CodeDepartement'][:10], y=df_grouped['mean'][:10], palette='viridis', order=df_grouped['CodeDepartement'][:10])
plt.title('Surface reelle bati moyenne par code departement')
plt.xlabel('Code département')
plt.ylabel('Surface reelle bati')
plt.show()
set_background('#E6E6FA')
df_grouped = df.groupby('CodeDepartement')['SurfaceReelleBati'].agg(['mean', 'count']).reset_index()
df_grouped = df_grouped.sort_values('mean', ascending=True)
fig=plt.figure(figsize=(14,8))
sns.barplot(x='CodeDepartement', y='mean', data=df_grouped[:10], palette='viridis', order=df_grouped['CodeDepartement'][:10])
plt.title('Surface reelle bati moyenne par code departement')
plt.xlabel('Code département')
plt.ylabel('Surface reelle bati')
plt.show()
set_background('#E6E6FA')
df_dept = df.groupby(['CodeDepartement'])['NombrePiecesPrincipales'].mean()
df_dept_sorted = df_dept.sort_values()
a=plt
plt.figure(figsize=(14,8))
plt.title('Nombre de pieces principales moyen par bien vendu par département')
sns.barplot(x=df_dept_sorted.index[:10], y=df_dept_sorted.values[:10], palette='viridis', order=df_dept_sorted.index[:10])
a.show()
set_background('#E6E6FA')
On remarque qu'il y a une corrélation entre le DAB représentant la surface réelle bâtiment moyenne des biens par département , et le DAB représentant le nombre de pièces principales moyen par bien vendu par département. En effet, on y retrouve en 1e et 2e département les plus faibles le 75 (Paris) et le 06 (Alpes Marîtimes). On retrouve d'autres département dans ces deux-ci, pas forcément dans le même ordre (92 ; 94 ; 93 ; 73...)
Cela prouve la cohérence de nos données, car cela semblait théoriquement évident qu'il y eut une corrélation entre ces données.
df['DateMutation'] = pd.to_datetime(df['DateMutation'])
# Créer un tableau avec le compte des ventes par mois
month_counts = df['DateMutation'].dt.month.value_counts().sort_index()
# Créer un graphique à barres
plt.figure(figsize=(20,10))
sns.barplot(x=month_counts.index, y=month_counts.values, palette=sns.cubehelix_palette(n_colors=len(month_counts.values)))
plt.title('Nombre de ventes par mois')
plt.xlabel('Mois')
plt.ylabel('Nombre de ventes')
plt.show()
set_background('#E6E6FA')
Observations On observe qu'il y a une forte baisse de vente de biens immobiliers en France lors du passage du mois de Juillet au mois d'Août. Nous observons également que globalement, il y a plus d'activités lors de la première moitié de l'année que pendant la seconde. Nous verrons la pertinence de cet échantillon de l'année 2022 en le comparant avec des échantillons d'années précédentes lors de la suite de notre étude analytique
plt.figure(figsize=(20,10))
sns.lineplot(x=month_counts.index, y=month_counts.values, palette=sns.cubehelix_palette(n_colors=len(month_counts.values)), linewidth=3)
plt.title('Nombre de ventes par mois', fontsize=22)
plt.xlabel('Mois', fontsize=18)
plt.ylabel('Nombre de ventes', fontsize=18)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.show()
set_background('#E6E6FA')
En se renseignant sur internet, on apprend rapidement et clairement qu'il y a une saisonnalité du marché immobilier, et qu'en effet "La fin de l'année le marché immobilier ralenti"
source : https://www.lemagdelimmobilier.com/dossier-900-saisonnalite-marche-immobilier-periode-vendre-acheter.html#:~:text=La%20fin%20de%20l'ann%C3%A9e%20%3A%20le%20ralentissement%20du%20march%C3%A9%20immobilier,march%C3%A9%20immobilier%20est%20moins%20actif.</i>
Maintenant, il est intéressant de savoir quels types de biens qui sont présents dans notre fichier en France en 2022 :
df["SurfaceTerrainRecorded"] = np.where(df["SurfaceTerrain"].isnull(), False, True)
# Calculate the percentage of records with surface terrain recorded
total_records = df.shape[0]
records_with_st = df[df["SurfaceTerrainRecorded"] == True].shape[0]
percent_with_st = (records_with_st / total_records) * 100
# Create a figure
fig = px.pie(values=[percent_with_st, 100 - percent_with_st],
names=["Avec Surface Terrain", "Sans Surface Terrain"],
title="Pourcentage de biens avec Surface Terrain enregistrée")
fig.update_layout(
font=dict(
size=16,
family="sans-serif",
color="#222222"
),
margin=dict(
t=50
)
)
fig.show()
set_background('#E6E6FA')
Mais cela ne nous renseigne pas sur la nature exacte des logements. On s'attend à avoir un nombre de maison/dépendance supérieur au nombre d'appartement après observation du Pie ci-dessus, mais déchiffrons la répartition exacte :
df_counts = df['TypeLocal'].value_counts().reset_index()
df_counts.columns = ['TypeLocal', 'counts']
fig = px.pie(df_counts, values='counts', names='TypeLocal', title='Répartition des biens immobiliers par TypeLocal')
fig.update_layout(
font=dict(
size=16,
family="sans-serif",
color="#222222"
),
margin=dict(
t=50
)
)
fig.show()
set_background('#E6E6FA')
Ces données sont cohérentes avec le graphique précédent : il n'y a pas plus d'appartement qu'il n'y a de biens sans Surface Terrain.
month_type_counts = df.groupby(['DateMutation', 'TypeLocal'])['TypeLocal'].count()
# Créer un tableau contenant le compte cumulé des ventes par mois et TypeLocal
month_type_cum_counts = month_type_counts.groupby(level=1).cumsum()
# Créer un graphique à aire multi-variables
plt.figure(figsize=(20,10))
sns.lineplot(x=month_type_cum_counts.index.get_level_values(0), y=month_type_cum_counts.values, hue=month_type_cum_counts.index.get_level_values(1), palette='rainbow', markers='o')
sns.set_style('darkgrid')
plt.title('Nombre de ventes par mois et TypeLocal (cumulé)', fontsize=20)
plt.xlabel('Mois', fontsize=15)
plt.ylabel('Nombre de ventes', fontsize=15)
plt.legend(fontsize=15)
plt.show()
set_background('#E6E6FA')
df_grouped = df.groupby('CodeDepartement')['TypeLocal'].value_counts().reset_index(name='count')
# remplacer les codes département par des nombres
# trier les données par CodeDepartement
df_grouped = df_grouped.sort_values("CodeDepartement")
# calculer le % d'appartement dans le nombre total de bien par appartement, et pareillement pour les maison
# créer une colonne pour le % total par code département
df_grouped['CodeDepartement'] = df_grouped['CodeDepartement'].astype('int64')
# trier les données par CodeDepartement
df_grouped = df_grouped.sort_values("CodeDepartement")
df_grouped['Total'] = df_grouped.groupby('CodeDepartement')['count'].transform('sum')
# calculer le % de chaque type de bien par code département
df_grouped['percentage'] = df_grouped['count'] / df_grouped['Total'] * 100
# trier les données par CodeDepartement
df_grouped = df_grouped.sort_values("CodeDepartement")
# ne mettre que Maison et Appartement à comparer sur le graphique
df_grouped = df_grouped[df_grouped.TypeLocal.isin(['Maison', 'Appartement'])]
# rendre ce graphique plus jolie
fig = px.scatter(df_grouped, x="CodeDepartement", y="TypeLocal", size="percentage",
color="TypeLocal", hover_name="CodeDepartement", size_max=30,
range_x=[0,101], range_y=["Appartement", "Maison"],
title='Répartition du couple Maison-Appartement par département',
color_discrete_map={'Appartement': 'red', 'Maison': 'green'},
template='plotly_dark', width=1000)
fig.show()
set_background('#E6E6FA')
from matplotlib import rcParams
ville_top_10 = df['Commune'].value_counts()[:7]
ville_top_10['PARIS'] = df[df['CodeDepartement'] == 75].shape[0]
ville_top_10['LYON'] = df[df['CodeDepartement'] == 69].shape[0]
ville_top_10['MARSEILLE'] = df[df['CodeDepartement'] == 13].shape[0]
ville_top_10 = ville_top_10.sort_values(ascending=False)
print("Le classement des 10 villes les plus récurrentes est le suivant :\n")
print("{:2s} {:20s} {:s}".format("#", "Ville", "Nombre de biens vendus"))
for i, classement in enumerate(ville_top_10.index):
print("{:2d} {:20s} {:d}".format(i+1, classement, int(ville_top_10[classement])))
rcParams['figure.facecolor'] = '#343131'
plt.style.use('dark_background')
fig1 = plt.figure(figsize=(15,15))
ax = plt.axes(projection='3d')
ax.bar3d(range(len(ville_top_10)), range(len(ville_top_10)), np.zeros(len(ville_top_10)), 1, 1, ville_top_10.values, shade=True, color=sns.color_palette("RdBu", n_colors=len(ville_top_10.values)))
ax.set_xticks(range(len(ville_top_10)))
ax.set_xticklabels(ville_top_10.index)
ax.set_title("Classement des 10 villes les plus récurrentes")
ax.set_xlabel("Ville")
ax.set_ylabel("Classement")
ax.set_zlabel("Nombre de biens vendus")
plt.show()
set_background('#E6E6FA')
Le classement des 10 villes les plus récurrentes est le suivant : # Ville Nombre de biens vendus 1 PARIS 41788 2 LYON 35878 3 MARSEILLE 28837 4 TOULOUSE 12556 5 NICE 11592 6 NANTES 7738 7 MONTPELLIER 7600 8 BORDEAUX 7564 9 RENNES 5202 10 LILLE 5085
df2018 = pd.read_csv('valeursfoncieres-2018.txt',sep='|')
df2018 = pd.read_csv("valeursfoncieres-2018.txt",sep="|",usecols=["No disposition",
"Date mutation",
"Nature mutation",
"Valeur fonciere",
"No voie",
"B/T/Q",
"Type de voie",
"Code voie",
"Voie",
"Code postal",
"Commune",
"Code departement",
"Code commune",
"Section",
"No plan",
"Nombre de lots",
"Code type local",
"Type local",
"Surface reelle bati",
"Nombre pieces principales",
"Nature culture",
"Surface terrain"])
df2018.columns = ["NoDisposition","DateMutation","NatureMutation","ValeurFonciere","NoVoie","BTQ","TypeDeVoie","CodeVoie","Voie","CodePostal","Commune","CodeDepartement","CodeCommune","Section","NoPlan","NombreDeLots","CodeTypeLocal","TypeLocal","SurfaceReelleBati","NombrePiecesPrincipales","NatureCulture","SurfaceTerrain"]
df2018["ValeurFonciere"] = df["ValeurFonciere"].apply(lambda x : x if isinstance(x, float) else float(x[:-3]))
#df2018["CodeDepartement"] = pd.to_numeric(df["CodeDepartement"], errors = 'coerce')
df2018.drop_duplicates(subset=['ValeurFonciere','CodeDepartement', 'DateMutation'], inplace=True)
set_background('#E9FDFF')
C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (14,18,23,24,26,28,29,31,32,33,41) have mixed types.Specify dtype option on import or set low_memory=False. C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (14,18) have mixed types.Specify dtype option on import or set low_memory=False.
df2019 = pd.read_csv('valeursfoncieres-2019.txt',sep='|')
df2019 = pd.read_csv("valeursfoncieres-2019.txt",sep="|",usecols=["No disposition",
"Date mutation",
"Nature mutation",
"Valeur fonciere",
"No voie",
"B/T/Q",
"Type de voie",
"Code voie",
"Voie",
"Code postal",
"Commune",
"Code departement",
"Code commune",
"Section",
"No plan",
"Nombre de lots",
"Code type local",
"Type local",
"Surface reelle bati",
"Nombre pieces principales",
"Nature culture",
"Surface terrain"])
df2019.columns = ["NoDisposition","DateMutation","NatureMutation","ValeurFonciere","NoVoie","BTQ","TypeDeVoie","CodeVoie","Voie","CodePostal","Commune","CodeDepartement","CodeCommune","Section","NoPlan","NombreDeLots","CodeTypeLocal","TypeLocal","SurfaceReelleBati","NombrePiecesPrincipales","NatureCulture","SurfaceTerrain"]
df2019["ValeurFonciere"] = df["ValeurFonciere"].apply(lambda x : x if isinstance(x, float) else float(x[:-3]))
#df2019["CodeDepartement"] = pd.to_numeric(df["CodeDepartement"], errors = 'coerce')
df2019.drop_duplicates(subset=['ValeurFonciere','CodeDepartement', 'DateMutation'], inplace=True)
set_background('#E9FDFF')
C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (18,23,24,26,28,31,33,41) have mixed types.Specify dtype option on import or set low_memory=False. C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (18) have mixed types.Specify dtype option on import or set low_memory=False.
df2020 = pd.read_csv('valeursfoncieres-2020.txt',sep='|')
df2020 = pd.read_csv("valeursfoncieres-2020.txt",sep="|",usecols=["No disposition",
"Date mutation",
"Nature mutation",
"Valeur fonciere",
"No voie",
"B/T/Q",
"Type de voie",
"Code voie",
"Voie",
"Code postal",
"Commune",
"Code departement",
"Code commune",
"Section",
"No plan",
"Nombre de lots",
"Code type local",
"Type local",
"Surface reelle bati",
"Nombre pieces principales",
"Nature culture",
"Surface terrain"])
df2020.columns = ["NoDisposition","DateMutation","NatureMutation","ValeurFonciere","NoVoie","BTQ","TypeDeVoie","CodeVoie","Voie","CodePostal","Commune","CodeDepartement","CodeCommune","Section","NoPlan","NombreDeLots","CodeTypeLocal","TypeLocal","SurfaceReelleBati","NombrePiecesPrincipales","NatureCulture","SurfaceTerrain"]
df2020["ValeurFonciere"] = df["ValeurFonciere"].apply(lambda x : x if isinstance(x, float) else float(x[:-3]))
#df2020["CodeDepartement"] = pd.to_numeric(df["CodeDepartement"], errors = 'coerce')
df2020.drop_duplicates(subset=['ValeurFonciere','CodeDepartement', 'DateMutation'], inplace=True)
set_background('#E9FDFF')
df2021 = pd.read_csv('valeursfoncieres-2021.txt',sep='|')
df2021 = pd.read_csv("valeursfoncieres-2021.txt",sep="|",usecols=["No disposition",
"Date mutation",
"Nature mutation",
"Valeur fonciere",
"No voie",
"B/T/Q",
"Type de voie",
"Code voie",
"Voie",
"Code postal",
"Commune",
"Code departement",
"Code commune",
"Section",
"No plan",
"Nombre de lots",
"Code type local",
"Type local",
"Surface reelle bati",
"Nombre pieces principales",
"Nature culture",
"Surface terrain"])
df2021.columns = ["NoDisposition","DateMutation","NatureMutation","ValeurFonciere","NoVoie","BTQ","TypeDeVoie","CodeVoie","Voie","CodePostal","Commune","CodeDepartement","CodeCommune","Section","NoPlan","NombreDeLots","CodeTypeLocal","TypeLocal","SurfaceReelleBati","NombrePiecesPrincipales","NatureCulture","SurfaceTerrain"]
df2021["ValeurFonciere"] = df["ValeurFonciere"].apply(lambda x : x if isinstance(x, float) else float(x[:-3]))
#df2021["CodeDepartement"] = pd.to_numeric(df["CodeDepartement"], errors = 'coerce')
df2021.drop_duplicates(subset=['ValeurFonciere','CodeDepartement', 'DateMutation'], inplace=True)
set_background('#E9FDFF')
C:\Users\sebas\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3146: DtypeWarning: Columns (18,23,24,26,28,29,30,31,33,41) have mixed types.Specify dtype option on import or set low_memory=False.
data_by_dep = df.groupby("CodeDepartement")["CodeDepartement"].count()
data_by_dep = pd.DataFrame({
"Departement" : list(data_by_dep.index),
"NbVente" : list(data_by_dep)})
data_by_dep.drop([91,92,93,94],axis=0,inplace=True)
data_by_dep21 = df2021.groupby("CodeDepartement")["CodeDepartement"].count()
data_by_dep21 = pd.DataFrame({
"Departement" : list(data_by_dep21.index),
"NbVente" : list(data_by_dep21)})
data_by_dep21.drop([91,92,93,94],axis=0,inplace=True)
data_by_dep20 = df2020.groupby("CodeDepartement")["CodeDepartement"].count()
data_by_dep20 = pd.DataFrame({
"Departement" : list(data_by_dep20.index),
"NbVente" : list(data_by_dep20)})
data_by_dep20.drop([91,92,93,94],axis=0,inplace=True)
data_by_dep19 = df2019.groupby("CodeDepartement")["CodeDepartement"].count()
data_by_dep19 = pd.DataFrame({
"Departement" : list(data_by_dep19.index),
"NbVente" : list(data_by_dep19)})
data_by_dep19.drop([91,92,93,94],axis=0,inplace=True)
data_by_dep18 = df2018.groupby("CodeDepartement")["CodeDepartement"].count()
data_by_dep18 = pd.DataFrame({
"Departement" : list(data_by_dep18.index),
"NbVente" : list(data_by_dep18)})
data_by_dep18.drop([91,92,93,94],axis=0,inplace=True)
set_background('#E9FDFF')
ValeurFonciereMoyenne = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne)})
#ValeurFonciereMoyenne.drop([95,98],axis=0,inplace=True)
ValeurFonciereMoyenne21 = df2021.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne21 = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne21.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne21)})
#ValeurFonciereMoyenne21.drop([95,98],axis=0,inplace=True)
ValeurFonciereMoyenne20 = df2020.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne20 = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne20.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne20)})
#ValeurFonciereMoyenne20.drop([95,98],axis=0,inplace=True)
ValeurFonciereMoyenne19 = df2019.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne19 = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne19.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne19)})
#ValeurFonciereMoyenne19.drop([95,98],axis=0,inplace=True)
ValeurFonciereMoyenne18 = df2018.groupby("CodeDepartement")["ValeurFonciere"].mean()
ValeurFonciereMoyenne18 = pd.DataFrame({
"Departement" : list(ValeurFonciereMoyenne18.index),
"ValeurFonciere" : list(ValeurFonciereMoyenne18)})
#ValeurFonciereMoyenne18.drop([95,98],axis=0,inplace=True)
set_background('#E9FDFF')
SurfaceBatieMoyenne = df.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
SurfaceBatieMoyenne = pd.DataFrame({
"Departement" : list(SurfaceBatieMoyenne.index),
"SurfaceBatie" : list(SurfaceBatieMoyenne)})
#SurfaceBatieMoyenne.drop([91,92,93,94],axis=0,inplace=True)
SurfaceBatieMoyenne21 = df2021.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
SurfaceBatieMoyenne21 = pd.DataFrame({
"Departement" : list(SurfaceBatieMoyenne21.index),
"SurfaceBatie" : list(SurfaceBatieMoyenne21)})
#SurfaceBatieMoyenne21.drop([91,92,93,94],axis=0,inplace=True)
SurfaceBatieMoyenne20 = df2020.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
SurfaceBatieMoyenne20 = pd.DataFrame({
"Departement" : list(SurfaceBatieMoyenne20.index),
"SurfaceBatie" : list(SurfaceBatieMoyenne20)})
#SurfaceBatieMoyenne20.drop([91,92,93,94],axis=0,inplace=True)
SurfaceBatieMoyenne19 = df2019.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
SurfaceBatieMoyenne19 = pd.DataFrame({
"Departement" : list(SurfaceBatieMoyenne19.index),
"SurfaceBatie" : list(SurfaceBatieMoyenne19)})
#SurfaceBatieMoyenne19.drop([91,92,93,94],axis=0,inplace=True)
SurfaceBatieMoyenne18 = df2018.groupby("CodeDepartement")["SurfaceReelleBati"].mean()
SurfaceBatieMoyenne18 = pd.DataFrame({
"Departement" : list(SurfaceBatieMoyenne18.index),
"SurfaceBatie" : list(SurfaceBatieMoyenne18)})
#SurfaceBatieMoyenne18.drop([91,92,93,94],axis=0,inplace=True)
set_background('#E9FDFF')
ValeurParSurface = pd.DataFrame({
"Departement" : SurfaceBatieMoyenne.Departement,
"ValeurParSurface" : (ValeurFonciereMoyenne.ValeurFonciere/SurfaceBatieMoyenne.SurfaceBatie)})
ValeurParSurface21 = pd.DataFrame({
"Departement" : SurfaceBatieMoyenne21.Departement,
"ValeurParSurface" : (ValeurFonciereMoyenne21.ValeurFonciere/SurfaceBatieMoyenne21.SurfaceBatie)})
ValeurParSurface20 = pd.DataFrame({
"Departement" : SurfaceBatieMoyenne20.Departement,
"ValeurParSurface" : (ValeurFonciereMoyenne20.ValeurFonciere/SurfaceBatieMoyenne.SurfaceBatie)})
ValeurParSurface19 = pd.DataFrame({
"Departement" : SurfaceBatieMoyenne19.Departement,
"ValeurParSurface" : (ValeurFonciereMoyenne19.ValeurFonciere/SurfaceBatieMoyenne.SurfaceBatie)})
ValeurParSurface18 = pd.DataFrame({
"Departement" : SurfaceBatieMoyenne18.Departement,
"ValeurParSurface" : (ValeurFonciereMoyenne18.ValeurFonciere/SurfaceBatieMoyenne.SurfaceBatie)})
set_background('#E9FDFF')
def plot_treemap(data):
fig = px.treemap(data, path=["NbVente","Departement"], values=data.NbVente,
title="Nombre de ventes par departement", color_discrete_sequence = px.colors.qualitative.Dark2)
fig.data[0].textinfo = 'label+text'
fig.show()
plot_treemap(data_by_dep)
set_background('#E6E6FA')
set_background('#E6E6FA')
m = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=data_by_dep,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=True
).add_to(m)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True,
control=False
).add_to(m)
folium.LayerControl().add_to(m)
m
set_background('#E6E6FA')
m1 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="choropleth",
data=ValeurFonciereMoyenne21,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=True
).add_to(m1)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True
).add_to(m1)
folium.LayerControl().add_to(m1)
m1
set_background('#E6E6FA')
m2 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="choropleth",
data=SurfaceBatieMoyenne21,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=True
).add_to(m2)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True
).add_to(m2)
folium.LayerControl().add_to(m2)
m2
set_background('#E6E6FA')
m3 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=ValeurParSurface,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Valeur Fonciere au m²",
overlay=True,
show=True
).add_to(m3)
folium.GeoJson("departements.geojson", name='Départements', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
control=False,
overlay=True
).add_to(m3)
m3
df2018['DateMutation'] = pd.to_datetime(df2018['DateMutation'])
df2019['DateMutation'] = pd.to_datetime(df2019['DateMutation'])
df2020['DateMutation'] = pd.to_datetime(df2020['DateMutation'])
df2021['DateMutation'] = pd.to_datetime(df2021['DateMutation'])
df['DateMutation'] = pd.to_datetime(df['DateMutation'])
# Créer un tableau avec le compte des ventes par mois
month_counts_2018 = df2018['DateMutation'].dt.month.value_counts().sort_index()
month_counts_2019 = df2019['DateMutation'].dt.month.value_counts().sort_index()
month_counts_2020 = df2020['DateMutation'].dt.month.value_counts().sort_index()
month_counts_2021 = df2021['DateMutation'].dt.month.value_counts().sort_index()
month_counts = df['DateMutation'].dt.month.value_counts().sort_index()
# Créer un graphique à barres
fig, ax = plt.subplots(3, 2, figsize=(20, 20))
sns.barplot(x=month_counts_2018.index, y=month_counts_2018.values, palette=sns.cubehelix_palette(n_colors=len(month_counts_2018.values)), ax=ax[0,0])
ax[0,0].set_title('Ventes en 2018')
ax[0,0].set_xlabel('Mois')
ax[0,0].set_ylabel('Nombre de ventes')
sns.barplot(x=month_counts_2019.index, y=month_counts_2019.values, palette=sns.cubehelix_palette(n_colors=len(month_counts_2019.values)), ax=ax[0,1])
ax[0,1].set_title('Ventes en 2019')
ax[0,1].set_xlabel('Mois')
ax[0,1].set_ylabel('Nombre de ventes')
sns.barplot(x=month_counts_2020.index, y=month_counts_2020.values, palette=sns.cubehelix_palette(n_colors=len(month_counts_2020.values)), ax=ax[1,0])
ax[1,0].set_title('Ventes en 2020')
ax[1,0].set_xlabel('Mois')
ax[1,0].set_ylabel('Nombre de ventes')
sns.barplot(x=month_counts_2021.index, y=month_counts_2021.values, palette=sns.cubehelix_palette(n_colors=len(month_counts_2021.values)), ax=ax[1,1])
ax[1,1].set_title('Ventes en 2021')
ax[1,1].set_xlabel('Mois')
ax[1,1].set_ylabel('Nombre de ventes')
sns.barplot(x=month_counts.index, y=month_counts.values, palette=sns.cubehelix_palette(n_colors=len(month_counts.values)), ax=ax[2,0])
ax[2,0].set_title('Ventes en 2022')
ax[2,0].set_xlabel('Mois')
ax[2,0].set_ylabel('Ventes en 2022')
fig.delaxes(ax[2, 1])
plt.show()
set_background('#E6E6FA')
On remarque une corrélation entres les graphiques 2018-2019-2020-2021 : il y a une forte hausse du nombre de vente de biens immobilier en décembre Une observation permet de relier cet échantillon au graphique de 2022 également, c'est la baisse soudaine en août par rapport à juillet. Cela s'explique certainement par les départs en vacances, et congés qu'ils entraînent.
import pandas as pd
# Calculer la valeur foncière moyenne par département pour chaque année
df2018_mean = df2018.groupby("CodeDepartement")["ValeurFonciere"].mean()
df2022_mean = df.groupby("CodeDepartement")["ValeurFonciere"].mean()
# Calculer la croissance de la valeur foncière moyenne en pourcentage pour chaque département
growth = (df2022_mean - df2018_mean) / df2018_mean * 100
# Trier les départements en fonction de la croissance de la valeur foncière moyenne (ordre décroissant)
sorted_departments = growth.sort_values(ascending=False)
# Créer un DataFrame avec le classement des départements et les valeurs correspondantes
table = pd.DataFrame({"Classement": range(1, len(sorted_departments) + 1),
"CodeDepartement": sorted_departments.index,
"ValeurFonciere2018": df2018_mean,
"ValeurFonciere2022": df2022_mean,
"CroissanceVF(%)": growth}).reset_index(drop=True)
# Ajuster l'index pour commencer à 1
table.index = table.index + 1
# Afficher l'intégralité du classement
pd.set_option('display.max_rows', None)
table
| Classement | CodeDepartement | ValeurFonciere2018 | ValeurFonciere2022 | CroissanceVF(%) | |
|---|---|---|---|---|---|
| 1 | 1 | 75 | 243587.661259 | 247912.148437 | 1.775331 |
| 2 | 2 | 78 | 110624.119118 | 109766.746425 | -0.775032 |
| 3 | 3 | 973 | 107563.426292 | 101878.381104 | -5.285296 |
| 4 | 4 | 971 | 105871.251554 | 145316.533482 | 37.257784 |
| 5 | 5 | 92 | 124898.334615 | 154302.704623 | 23.542644 |
| 6 | 6 | 91 | 364756.944219 | 399971.030416 | 9.654124 |
| 7 | 7 | 972 | 429010.960048 | 128912.255157 | -69.951291 |
| 8 | 8 | 69 | 447830.932667 | 99010.047289 | -77.891200 |
| 9 | 9 | 94 | 233119.187288 | 95139.406498 | -59.188513 |
| 10 | 10 | 974 | 104813.423840 | 130015.086634 | 24.044308 |
| 11 | 11 | 59 | 97468.232458 | 127370.822498 | 30.679319 |
| 12 | 12 | 95 | 128174.603474 | 105701.513155 | -17.533185 |
| 13 | 13 | 90 | 219323.363473 | 348162.992361 | 58.744142 |
| 14 | 14 | 25 | 385978.743945 | 210983.100588 | -45.338156 |
| 15 | 15 | 13 | 214082.486859 | 88718.903897 | -58.558542 |
| 16 | 16 | 21 | 166753.349709 | 119857.672799 | -28.122780 |
| 17 | 17 | 26 | 170276.996238 | 218050.620265 | 28.056417 |
| 18 | 18 | 44 | 282335.454766 | 106201.715719 | -62.384563 |
| 19 | 19 | 74 | 126132.768466 | 99399.864354 | -21.194258 |
| 20 | 20 | 83 | 112266.359964 | 172855.688156 | 53.969264 |
| 21 | 21 | 4 | 131251.626645 | 158057.164667 | 20.423014 |
| 22 | 22 | 33 | 161263.671685 | 54256.995672 | -66.355103 |
| 23 | 23 | 56 | 150404.937322 | 128845.718519 | -14.334116 |
| 24 | 24 | 60 | 106475.002886 | 184236.954968 | 73.033059 |
| 25 | 25 | 64 | 132191.694130 | 195838.064625 | 48.147027 |
| 26 | 26 | 11 | 188801.913806 | 172381.345105 | -8.697247 |
| 27 | 27 | 17 | 173426.403308 | 172463.295927 | -0.555341 |
| 28 | 28 | 30 | 189552.848425 | 165580.438907 | -12.646821 |
| 29 | 29 | 10 | 162200.835101 | 204052.373206 | 25.802295 |
| 30 | 30 | 45 | 221638.978075 | 254267.232747 | 14.721352 |
| 31 | 31 | 5 | 224812.340534 | 136233.162181 | -39.401386 |
| 32 | 32 | 93 | 245856.150094 | 335297.351810 | 36.379485 |
| 33 | 33 | 22 | 350338.663500 | 233858.703251 | -33.247818 |
| 34 | 34 | 31 | 313329.607180 | 233804.039068 | -25.380802 |
| 35 | 35 | 84 | 282953.639506 | 84650.640521 | -70.083212 |
| 36 | 36 | 6 | 247762.285599 | 186368.271343 | -24.779403 |
| 37 | 37 | 48 | 208789.134946 | 201892.913115 | -3.302960 |
| 38 | 38 | 62 | 255928.046137 | 116873.811102 | -54.333332 |
| 39 | 39 | 77 | 210064.342256 | 217473.062421 | 3.526881 |
| 40 | 40 | 40 | 139332.159683 | 129557.804973 | -7.015146 |
| 41 | 41 | 1 | 190126.035447 | 155482.165114 | -18.221529 |
| 42 | 42 | 54 | 206348.713666 | 84242.683259 | -59.174602 |
| 43 | 43 | 28 | 174354.565754 | 257471.267009 | 47.671078 |
| 44 | 44 | 2 | 146439.980488 | 181511.305580 | 23.949283 |
| 45 | 45 | 47 | 164177.424612 | 111163.549020 | -32.290600 |
| 46 | 46 | 38 | 146504.837793 | 143169.718954 | -2.276456 |
| 47 | 47 | 3 | 78032.006231 | 83231.167300 | 6.662857 |
| 48 | 48 | 41 | 222268.316311 | 179402.424958 | -19.285651 |
| 49 | 49 | 27 | 271313.671731 | 130289.607747 | -51.978237 |
| 50 | 50 | 63 | 248099.884527 | 184057.959338 | -25.812960 |
| 51 | 51 | 29 | 211527.107649 | 77196.286455 | -63.505251 |
| 52 | 52 | 73 | 188744.651302 | 121702.111811 | -35.520233 |
| 53 | 53 | 24 | 163153.018217 | 165338.492136 | 1.339524 |
| 54 | 54 | 12 | 118113.575250 | 79095.701987 | -33.034199 |
| 55 | 55 | 42 | 152191.676860 | 207245.105947 | 36.173745 |
| 56 | 56 | 49 | 191211.034239 | 91657.873816 | -52.064548 |
| 57 | 57 | 19 | 144135.147318 | 272317.030827 | 88.931732 |
| 58 | 58 | 37 | 153880.085418 | 208040.460732 | 35.196481 |
| 59 | 59 | 35 | 172022.788818 | 101398.690295 | -41.055083 |
| 60 | 60 | 51 | 182717.144567 | 192239.106897 | 5.211313 |
| 61 | 61 | 70 | 150219.119110 | 131756.724908 | -12.290309 |
| 62 | 62 | 72 | 281429.372004 | 380442.567259 | 35.182254 |
| 63 | 63 | 16 | 347695.891252 | 119943.968264 | -65.503197 |
| 64 | 64 | 46 | 332400.033224 | 160528.697138 | -51.706173 |
| 65 | 65 | 55 | 190329.424591 | 374677.028878 | 96.857123 |
| 66 | 66 | 34 | 114727.458712 | 83730.593320 | -27.017826 |
| 67 | 67 | 53 | 195620.383998 | 121530.970157 | -37.874076 |
| 68 | 68 | 71 | 187219.655405 | 135474.350692 | -27.638821 |
| 69 | 69 | 32 | 326424.041135 | 280008.564122 | -14.219381 |
| 70 | 70 | 61 | 237753.702759 | 350992.574463 | 47.628647 |
| 71 | 71 | 76 | 115655.055795 | 914984.534906 | 691.132328 |
| 72 | 72 | 14 | 370381.207416 | 204939.028334 | -44.668081 |
| 73 | 73 | 85 | 301814.218076 | 316320.979728 | 4.806520 |
| 74 | 74 | 79 | 132570.439331 | 438894.919060 | 231.065448 |
| 75 | 75 | 80 | 213399.798411 | 106833.194191 | -49.937537 |
| 76 | 76 | 66 | 302569.535069 | 150831.595035 | -50.149775 |
| 77 | 77 | 50 | 308334.503199 | 141375.185595 | -54.148762 |
| 78 | 78 | 58 | 375915.352224 | 155190.386685 | -58.716667 |
| 79 | 79 | 81 | 237558.532239 | 330841.680350 | 39.267437 |
| 80 | 80 | 39 | 226306.453774 | 251829.955543 | 11.278292 |
| 81 | 81 | 15 | 318674.238168 | 173638.269953 | -45.512298 |
| 82 | 82 | 82 | 332291.780345 | 123342.177013 | -62.881364 |
| 83 | 83 | 43 | 408422.396590 | 115172.291460 | -71.800692 |
| 84 | 84 | 9 | 504837.343429 | 97551.137591 | -80.676719 |
| 85 | 85 | 18 | 340468.744370 | 121253.946274 | -64.386174 |
| 86 | 86 | 86 | 90605.096916 | 161511.591216 | 78.258836 |
| 87 | 87 | 52 | 134421.326181 | 321851.608606 | 139.434930 |
| 88 | 88 | 89 | 236491.462014 | 697498.661996 | 194.936086 |
| 89 | 89 | 65 | 315082.488045 | 388386.894440 | 23.265148 |
| 90 | 90 | 23 | 229683.088849 | 441478.126844 | 92.211855 |
| 91 | 91 | 7 | 180842.590982 | 340375.912540 | 88.216675 |
| 92 | 92 | 36 | 113132.308832 | 348547.506135 | 208.088388 |
| 93 | 93 | 87 | 116181.126824 | 229920.346642 | 97.898190 |
| 94 | 94 | 8 | 120996.780749 | 386368.529964 | 219.321330 |
| 95 | 95 | 88 | 124463.200447 | 238693.976736 | 91.778755 |
| 96 | 96 | 29 | 179080.854839 | NaN | NaN |
| 97 | 97 | 2A | 157909.476008 | NaN | NaN |
| 98 | 98 | 2B | 193100.847667 | NaN | NaN |
| 99 | 99 | 30 | 176484.292477 | NaN | NaN |
set_background('#E6E6FA')
m = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=data_by_dep,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=True
).add_to(m)
folium.Choropleth("departements.geojson",
name="2021",
data=data_by_dep21,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=False
).add_to(m)
folium.Choropleth("departements.geojson",
name="2020",
data=data_by_dep20,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=False
).add_to(m)
folium.Choropleth("departements.geojson",
name="2019",
data=data_by_dep19,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=False
).add_to(m)
folium.Choropleth("departements.geojson",
name="2018",
data=data_by_dep18,
columns=["Departement", "NbVente"],
key_on="feature.properties.code",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
nan_fill_color = "grey",
legend_name="Nb de vente",
overlay=True,
show=False
).add_to(m)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True,
control=False
).add_to(m)
folium.LayerControl().add_to(m)
m
set_background('#E6E6FA')
m2 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=SurfaceBatieMoyenne,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=True
).add_to(m2)
folium.Choropleth("departements.geojson",
name="2021",
data=SurfaceBatieMoyenne21,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=False
).add_to(m2)
folium.Choropleth("departements.geojson",
name="2020",
data=SurfaceBatieMoyenne20,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=False
).add_to(m2)
folium.Choropleth("departements.geojson",
name="2019",
data=SurfaceBatieMoyenne19,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=False
).add_to(m2)
folium.Choropleth("departements.geojson",
name="2018",
data=SurfaceBatieMoyenne18,
columns=["Departement", "SurfaceBatie"],
key_on="feature.properties.code",
fill_color= 'PuOr',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Surface Batie",
overlay=True,
show=False
).add_to(m2)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True,
control=False
).add_to(m2)
folium.LayerControl().add_to(m2)
m2
set_background('#E6E6FA')
m1 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=ValeurFonciereMoyenne,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=True
).add_to(m1)
folium.Choropleth("departements.geojson",
name="2021",
data=ValeurFonciereMoyenne21,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=False
).add_to(m1)
folium.Choropleth("departements.geojson",
name="2020",
data=ValeurFonciereMoyenne20,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=False
).add_to(m1)
folium.Choropleth("departements.geojson",
name="2019",
data=ValeurFonciereMoyenne19,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=False
).add_to(m1)
folium.Choropleth("departements.geojson",
name="2018",
data=ValeurFonciereMoyenne18,
columns=["Departement", "ValeurFonciere"],
key_on="feature.properties.code",
fill_color= 'OrRd',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="ValeurFonciere",
overlay=True,
show=False
).add_to(m1)
folium.GeoJson("departements.geojson", name='geojson', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
overlay=True,
control=False
).add_to(m1)
folium.LayerControl().add_to(m1)
m1
set_background('#E6E6FA')
m3 = folium.Map(location=[47, 3],
zoom_start=6, control_scale=True)
folium.Choropleth("departements.geojson",
name="2022",
data=ValeurParSurface,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="Valeur Fonciere au m²",
overlay=True,
show=True
).add_to(m3)
folium.Choropleth("departements.geojson",
name="2021",
data=ValeurParSurface21,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
overlay=True,
show=False
).add_to(m3)
folium.Choropleth("departements.geojson",
name="2020",
data=ValeurParSurface20,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
overlay=True,
show=False
).add_to(m3)
folium.Choropleth("departements.geojson",
name="2019",
data=ValeurParSurface19,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
overlay=True,
show=False
).add_to(m3)
folium.Choropleth("departements.geojson",
name="2018",
data=ValeurParSurface18,
columns=["Departement", "ValeurParSurface"],
key_on="feature.properties.code",
fill_color= 'Paired',
nan_fill_color = "grey",
fill_opacity=0.7,
line_opacity=0.2,
overlay=True,
show=False
).add_to(m3)
folium.GeoJson("departements.geojson", name='Départements', zoom_on_click = True,
tooltip=folium.GeoJsonTooltip(fields=['nom','code']),
style_function= lambda feature: {'fillOpacity':0,'weight':0.5,'color':f'#A8AFC3'},
show=True,
control=False,
overlay=True
).add_to(m3)
folium.LayerControl().add_to(m3)
m3